﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Text;
using Microsoft.Windows.Controls;
using System.Windows.Media.Imaging;
using Ranet.AgOlap.Core.DataDescription;
using Galaktika.BI.Silverlight.Controls.MemberChoice.Info;
using Galaktika.BI.Silverlight.Controls.MemberChoice.Tree;
using Galaktika.BI.Runtime.Services;
using System.ComponentModel;
using Galaktika.BI.Silverlight.Controls.MemberChoice.ClientServer;
using Galaktika.BI.Runtime;
using Galaktika.BI.Silverlight.Controls.General.Tree;
using Galaktika.BI.Silverlight.Commands;
using System.Threading;

namespace Galaktika.BI.Silverlight.Controls.MemberChoice
{
    // Подумать:
    // Как сделать переход из дерева найденных на дерево выбора, по двойному клику идет раскрытие узла - значит это нам не подходит
    // 
    //
    //

    public partial class MemberChoiceControl : UserControl
    {
        public MemberChoiceControl()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(MemberChoiceControl_Loaded);
            Tree.SpecialNodeExpanded += new EventHandler(node_SpecialNodeExpanded);
        }

        public IBindingContext Context { get; set; }

        #region Свойства

        #region Свойства для настройки на OLAP
        /// <summary>
        /// 
        /// </summary>
        private String m_Connection = String.Empty;
        /// <summary>
        /// 
        /// </summary>
        public String Connection
        {
            get
            {
                return m_Connection;
            }
            set
            {
                m_Connection = value;
            }
        }

        /// <summary>
        /// Имя OLAP куба
        /// </summary>
        String m_CubeName = String.Empty;
        /// <summary>
        /// Имя OLAP куба
        /// </summary>
        public String CubeName
        {
            get
            {
                return this.m_CubeName;
            }
            set
            {
                m_CubeName = value;
            }
        }

        /// <summary>
        /// Имя иерархии измерения
        /// </summary>
        String m_HierarchyName = String.Empty;
        /// <summary>
        /// Имя иерархии измерения
        /// </summary>
        public String HierarchyName
        {
            get
            {
                return this.m_HierarchyName;
            }
            set
            {
                m_HierarchyName = value;
            }
        }
        #endregion Свойства для настройки на OLAP

        #region Частичная загрузка
        private int m_Step = 100;
        /// <summary>
        /// Шаг при частичной загрузке
        /// </summary>
        public int Step
        {
            get
            {
                if (m_Step <= 0)
                    return 1;
                else
                    return m_Step;
            }
            set
            {
                m_Step = value;
            }
        }

        /// <summary>
        /// Использование частичной загрузки
        /// </summary>
        private bool useStepLoading = true;
        /// <summary>
        /// Использование частичной загрузки
        /// </summary>
        public bool UseStepLoading
        {
            get
            {
                return useStepLoading;
            }
            set
            {
                useStepLoading = value;
            }
        }
        #endregion Частичная загрузка

        private string startLevelUniqueName = String.Empty;
        /// <summary>
        /// Уникальное имя уровня, начиная с которого элементы будут отображаться в дереве
        /// </summary>
        public string StartLevelUniqueName
        {
            get
            {
                return startLevelUniqueName;
            }
            set
            {
                startLevelUniqueName = value;
                //rootTreeListNodesCount = -1;
            }
        }

        private string startMemberUniqueName = String.Empty;
        /// <summary>
        /// Уникальное имя элемента, дочерние которого элементы будут отображаться в дереве
        /// </summary>
        public string StartMemberUniqueName
        {
            set
            {
                startMemberUniqueName = value;
            }
            get
            {
                return startMemberUniqueName;
            }
        }
        #endregion Свойства

        void MemberChoiceControl_Loaded(object sender, RoutedEventArgs e)
        {
            //StartLevelUniqueName = "[Product].[Product Categories].[Subcategory]";

            //Initialize("Provider=msolap.3;Data Source=dpp-675;Initial Catalog = Adventure Works DW;", "[Product].[Product Categories]", "Adventure Works");
        }

        public void Initialize()//(String connection, String hierarchyUniqueName, String cubeName)
        {
            //if (String.IsNullOrEmpty(connection))
            //    throw new ArgumentNullException("connection");
            //if (String.IsNullOrEmpty(hierarchyUniqueName))
            //    throw new ArgumentNullException("hierarchyUniqueName");
            //if (String.IsNullOrEmpty(hierarchyUniqueName))
            //    throw new ArgumentNullException("cubeName");

            //m_Connection = connection;
            //m_HierarchyName = hierarchyUniqueName;
            //m_CubeName = cubeName;

            RefreshTree(true);
        }

        long m_RootMembersCubeCount = 0;

        /// <summary>
        /// Перерисовывает дерево. Информация о выбранных элементах остается
        /// </summary>
        private void RefreshTree(bool reloadSelection)
        {
            ////Чистим дерево
            //Tree.Nodes.Clear();
            //m_TreeNodes.Clear();

            //if (reloadSelection)
            //{
            //    //Формируем иерархию OlapMemberInfo
            //    OlapMemberInfoHierarchy = BuildHierarсhyBySelection(SelectedInfo);
            //}

            Tree.Items.Clear();
            m_TreeNodes.Clear();
            m_RootMembersCubeCount = 0;

            GetRootMembersCount();
        }

        private void GetRootMembersCount()
        {
            Tree.IsWaiting = true;

            IUserTaskManager taskManager = (IUserTaskManager)Context.Services.GetService(typeof(IUserTaskManager));
            if (taskManager != null)
            {
                InvokeSchema schema = CommandBuilder.CreateGetRootMembersCountSchema((string)this.Context.UserData["_$Id"], m_Connection, m_CubeName, HierarchyName, StartLevelUniqueName, StartMemberUniqueName);

                taskManager.ProcessTaskItem(Localization.AppTask_CalcRootMembersCount,
                    new WaitCallback(InvokeCommandBySchema),
                    new MemberChoiceInvokeSchemaWrapper(schema));
            }
        }

        void Service_GetRootMembersCountCompleted(InvokeResultSchema res, MemberTreeNode node)
        {
            Tree.IsWaiting = false;
            Tree.IsFullLoaded = true;

            m_RootMembersCubeCount = 0;
            if (res.Content != null)
            {
                m_RootMembersCubeCount = long.Parse(res.Content);
            }

            //Получаем элементы
            if (useStepLoading)
                LoadRootMembers(0, Step);
            else
                LoadRootMembers(-1, -1);
        }

        private void LoadRootMembers(long begin, long count)
        {
            Tree.IsWaiting = true;

            IUserTaskManager taskManager = (IUserTaskManager)Context.Services.GetService(typeof(IUserTaskManager));
            if (taskManager != null)
            {
                InvokeSchema schema = CommandBuilder.CreateGetRootMembersSchema((string)this.Context.UserData["_$Id"], m_Connection, m_CubeName, HierarchyName, StartLevelUniqueName, StartMemberUniqueName, begin, count);

                taskManager.ProcessTaskItem(Localization.AppTask_DownloadingRootMembers,
                    new WaitCallback(InvokeCommandBySchema),
                    new MemberChoiceInvokeSchemaWrapper(schema));
            }
        }

        void service_GetRootMembersCompleted(InvokeResultSchema res, MemberTreeNode node)
        {
            Tree.IsWaiting = false;
            Tree.IsFullLoaded = true;

            List<MemberDescriptionWrapper> members = UnPackMembers(res.Content);

            CreateChildNodes(null, members);
        }

        List<MemberDescriptionWrapper> UnPackMembers(String str)
        {
            List<MemberDescriptionWrapper> members = null;
            if (!String.IsNullOrEmpty(str))
            {
                try
                {
                    members = XmlUtility.XmlStr2Obj<List<MemberDescriptionWrapper>>(str);
                }
                catch
                {
                    return null;
                }
            }
            return members;
        }

        /// <summary>
        /// Иерархия OlapMemberInfo
        /// </summary>
        private RootOlapMemberInfo m_OlapMemberInfoHierarchy = null;
        private RootOlapMemberInfo OlapMemberInfoHierarchy
        {
            get
            {
                if (m_OlapMemberInfoHierarchy == null)
                {
                    m_OlapMemberInfoHierarchy = new RootOlapMemberInfo(MemberDescriptionWrapper.Empty, Mode);
                }
                return m_OlapMemberInfoHierarchy;
            }
        }

        /// <summary>
        /// Режим работы 
        /// </summary>
        private Modes mode = Modes.BM;

        private Modes Mode
        {
            get
            {
                return mode;
            }
        }

        /// <summary>
        /// Режим выбора: true - множественный выбор, false - одиночный выбор
        /// </summary>
        private bool m_MultiSelect = true;
        public bool MultiSelect
        {
            set
            {
                m_MultiSelect = value;
                //if (value)
                //{
                //    OkButton.Visibility = Visibility.Visible;
                //}
                //else 
                //{
                //    OkButton.Visibility = Visibility.Collapsed;
                //}
            }
            get
            {
                return m_MultiSelect;
            }
        }

        Dictionary<String, MemberTreeNode> m_TreeNodes = new Dictionary<String, MemberTreeNode>();

        void CreateChildNodes(MemberTreeNode parent, List<MemberDescriptionWrapper> members)
        {
            if (members == null)
                return;

            List<OlapMemberInfo> infos = new List<OlapMemberInfo>();
            List<OlapMemberInfo> to_Collapse = new List<OlapMemberInfo>();

            foreach (MemberDescriptionWrapper wrapper in members)
            {
                // Каждый из элементов помещаем в иерархию
                OlapMemberInfo info = OlapMemberInfoHierarchy.AddMemberToHierarchy(wrapper);
                if (info != null)
                {
                    if (info.CubeChildrenCount != wrapper.RealChildrenCount)
                    {
                        to_Collapse.Add(info);
                        info.CubeChildrenCount = wrapper.RealChildrenCount;
                    }
                    infos.Add(info);
                }
            }

            //Если известен родительский узел дерева. То получаем его OlapMemberInfo
            if (parent != null)
            {
                parent.IsWaiting = false;
                parent.IsFullLoaded = true;
            }

            foreach (OlapMemberInfo info in infos)
            {
                MemberTreeNode node = null;

                //Если родительский узел не задан, то узел добавится в корень
                if (m_TreeNodes.ContainsKey(info.UniqueName))
                {
                    node = m_TreeNodes[info.UniqueName];
                    if (to_Collapse.Contains(info))
                    {
                        //Сворачиваем узел, чтобы при разворачивании зачиталось новое количество дочерних
                        if (node != null)
                        {
                            node.IsExpanded = false;
                            //Удаляем дочерние узлы дерева
                            node.Items.Clear();
                            // Обновляем информацию о количестве дочерних
                            node.MemberInfo.CubeChildrenCount = info.CubeChildrenCount;
                        }
                    }

                }

                if (node == null)
                {
                    node = new MemberTreeNode(info, MultiSelect);
                    node.SpecialNodeExpanded += new EventHandler(node_SpecialNodeExpanded);
                    node.Expanded += new RoutedEventHandler(MemberNode_Expanded);

                    m_TreeNodes[info.UniqueName] = node;
                    //memberInfo.StateChanged += new OlapMemberInfo.StateChangedEventHandler(memberInfo_StateChanged);

                    if (parent == null)
                        Tree.Items.Add(node);
                    else
                        parent.Items.Add(node);
                }

                //            SetNodeIcon(node, memberInfo);

                //            //Если нужно выводить элемнты ТОЛЬКО верхнего уровня
                //            if (onlyFirstLevelMembers == false)
                //            {
                //Если есть дочерние, то добавляем фиктивный узел для отображения [+] напротив данного узла
                if (info.HasChildren)
                {
                    node.IsWaiting = true;
                }
                //}
            }

            //Если режим Частичной загрузки, то сверяем количество загруженных элементов и количество элементов в кубе
            if (useStepLoading)
            {
                if (AllChildrenMembersAddedToTreeNode(parent) == false)
                {
                    if (parent != null)
                        parent.IsFullLoaded = false;
                    else
                    {
                        Tree.IsFullLoaded = false;
                    }
                }
                else
                {
                    int i = 0;
                }
            }

            Tree.UpdateLayout();
        }

        void node_SpecialNodeExpanded(object sender, EventArgs e)
        {
            TreeViewItem node = sender as TreeViewItem;
            if (node == null)
                return;
            //Количество загруженных узлов - это количество узлов - 2 (узел "Загрузить далее", узел "Загрузить все")
            long loadedChildrenCount = 0;

            TreeViewItem parent = node.Parent as TreeViewItem;
            if (parent == null)
            {
                // Догружаем в корень дерева
                loadedChildrenCount = Tree.Items.Count - 2;
            }
            else
            {
                //Догружаем в элемент
                loadedChildrenCount = parent.Items.Count - 2;
            }

            LoadNextTreeNode loadNext = sender as LoadNextTreeNode;
            if (loadNext != null)
            {
                if (parent != null)
                {
                    MemberTreeNode parentNode = parent as MemberTreeNode;
                    if (parentNode != null)
                    {
                        //Зачитываем дочерних 
                        LoadChildren(parentNode, loadedChildrenCount, Step);
                    }
                }
                else
                {
                    //Зачитываем дочерних - как для корневого узла
                    LoadRootMembers(loadedChildrenCount, Step);
                }
                return;
            }

            LoadAllTreeNode loadAll = sender as LoadAllTreeNode;
            if (loadAll != null)
            {
                long count = 0;
                if (parent != null)
                {
                    MemberTreeNode parentNode = parent as MemberTreeNode;
                    if (parentNode != null)
                    {
                        count = parentNode.MemberInfo.CubeChildrenCount - loadedChildrenCount;
                        //Зачитываем дочерних 
                        LoadChildren(parentNode, loadedChildrenCount, count);
                    }
                }
                else
                {
                    count = m_RootMembersCubeCount - loadedChildrenCount;
                    //Зачитываем дочерних - как для корневого узла
                    LoadRootMembers(loadedChildrenCount, count);
                }
                return;
            }
        }

        /// <summary>
        /// Проверяет все ли дочерние мемберы для указанного узла добавлены в дерево
        /// </summary>
        /// <param name="parent"></param>
        /// <returns></returns>
        private bool AllChildrenMembersAddedToTreeNode(MemberTreeNode node)
        {
            long loadedChildrenCount = 0;
            long cubeChildrenCount = 0;
            if (node == null)	// - корневой узел
            {
                loadedChildrenCount = Tree.Items.Count;
                cubeChildrenCount = m_RootMembersCubeCount;

                if (loadedChildrenCount < cubeChildrenCount)
                {
                    return false;
                }
                else
                    return true;
            }
            else
            {
                loadedChildrenCount = node.Items.Count;

                OlapMemberInfo info = node.MemberInfo;
                cubeChildrenCount = info.CubeChildrenCount;

                if (loadedChildrenCount < cubeChildrenCount)
                {
                    return false;
                }
                else
                    return true;
            }
        }

        void MemberNode_Expanded(object sender, RoutedEventArgs e)
        {
            MemberTreeNode node = sender as MemberTreeNode;
            if (node == null)
                return;

            if (node.IsInitialized)
            {
                // В случае если узел уже инициализировался и дочерних в кубе у него нет, то при отключенном множетвенном выборе двойной клик считаем выбором элемента
                if (MultiSelect == false && node.MemberInfo != null && node.MemberInfo.CubeChildrenCount == 0)
                {
                    ApplyMembersSelection();
                }
            }
            else
            {
                BeforeExpandNode(node);
            }

            //Tree.SetFocusedNode(e.Node);
        }

        /// <summary>
        /// Раскрытие узла дерева
        /// </summary>
        /// <param name="node"></param>
        private void BeforeExpandNode(MemberTreeNode node)
        {
            node.Items.Clear();
            node.IsWaiting = true;

            //Загружаем дочерние элементы для данного узла
            if (useStepLoading)
            {
                LoadChildren(node, 0, Step);
            }
            else
            {
                LoadChildren(node);
            }
        }

        /// <summary>
        /// Загружает все дочерние элементы для указанного
        /// </summary>
        private void LoadChildren(MemberTreeNode item)
        {
            LoadChildren(item, -1, -1);
        }

        /// <summary>
        /// Загружает <paramref name="count"/> дочерних элементов для элемента с указанным <paramref name="uniqueName"/>, начиная c <paramref name="begin"/>.
        /// </summary>
        /// <param name="begin">индекс начала</param>
        /// <param name="count">количество</param>
        private void LoadChildren(MemberTreeNode item, long begin, long count)
        {
            if (item == null)
                return;

            OlapMemberInfo info = item.MemberInfo;

            IUserTaskManager taskManager = (IUserTaskManager)Context.Services.GetService(typeof(IUserTaskManager));
            if (taskManager != null)
            {
                InvokeSchema schema = CommandBuilder.CreateGetChildrenMembersSchema((string)this.Context.UserData["_$Id"], m_Connection, m_CubeName, HierarchyName, info.UniqueName, StartLevelUniqueName, StartMemberUniqueName, begin, count);

                taskManager.ProcessTaskItem(String.Format(Localization.AppTask_DownloadingChildrenMembersFor, info.Text),
                    new WaitCallback(InvokeCommandBySchema),
                    new MemberChoiceInvokeSchemaWrapper(schema, item));
            }
        }

        private void InvokeCommandBySchema(object state)
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(InvokeCommand), state);
        }

        void InvokeCommand(object state)
        {
            MemberChoiceInvokeSchemaWrapper wrapper = state as MemberChoiceInvokeSchemaWrapper;
            if (wrapper != null)
            {
                InvokeSchema schema = wrapper.Schema;
                using (SyncDataService ds = new SyncDataService())
                {
                    InvokeResultSchema res = ds.InvokeCommand(schema);

                    if (ds.Error != null)
                    {
                        LogException(ds.Error);
                        return;
                    }

                    String str = wrapper.Schema[KnownInvokeArgs.MemberChoiceQueryInfo];
                    MemberChoiceQueryArgs args = XmlUtility.XmlStr2Obj<MemberChoiceQueryArgs>(str);
                    switch (args.QueryType)
                    {
                        case MemberChoiceQueryType.GetChildrenMembers:
                            this.Dispatcher.BeginInvoke(delegate { Service_GetChildrenMembersCompleted(res, wrapper.Node); });
                            break;
                        case MemberChoiceQueryType.GetRootMembers:
                            this.Dispatcher.BeginInvoke(delegate { service_GetRootMembersCompleted(res, wrapper.Node); });
                            break;
                        case MemberChoiceQueryType.GetRootMembersCount:
                            this.Dispatcher.BeginInvoke(delegate { Service_GetRootMembersCountCompleted(res, wrapper.Node); });
                            break;
                        case MemberChoiceQueryType.FindMembers:
                            this.Dispatcher.BeginInvoke(delegate { FindMembers_InvokeCommandCompleted(res, wrapper.Node); });
                            break;

                    }
                }
            }
        }

        private bool LogException(Exception ex)
        {
            IOutputService log = (IOutputService)Context.Services.GetService(typeof(IOutputService));
            if (log != null)
            {
                log.WriteException(ex);
                return true;
            }
            return false;
        }

        void Service_GetChildrenMembersCompleted(InvokeResultSchema res, MemberTreeNode node)
        {
            List<MemberDescriptionWrapper> members = UnPackMembers(res.Content);

            CreateChildNodes(node, members);
        }

        public static BitmapImage GetIconImage(OlapMemberInfo memberInfo)
        {
            if (memberInfo == null)
                return null;

            BitmapImage res = null;
            if (memberInfo.Mode == Modes.BM)
            {
                switch (memberInfo.SelectState)
                {
                    case SelectStates.Not_Initialized:
                    case SelectStates.Not_Selected:
                        res = UriResources.Images.NotSelected16;
                        break;
                    case SelectStates.Selected_Self:
                    case SelectStates.Selected_By_Parent:
                        res = UriResources.Images.Selected16;
                        break;
                    case SelectStates.Selected_With_Children:
                    case SelectStates.Selected_By_Parent_With_Children:
                        res = UriResources.Images.SelectedChildren16;
                        break;
                    case SelectStates.Labeled_As_Parent:
                        res = UriResources.Images.HasSelectedChildren16;
                        break;
                    case SelectStates.Selected_With_Children_Has_Excluded:
                    case SelectStates.Selected_By_Parent_With_Children_Has_Excluded:
                        res = UriResources.Images.HasExcludedChildren16;
                        break;
                    default:
                        break;
                }
            }

            if (memberInfo.Mode == Modes.Rows_Area)
            {
                switch (memberInfo.SelectState)
                {
                    case SelectStates.Not_Initialized:
                    case SelectStates.Not_Selected:
                        res = UriResources.Images.NotSelected16;
                        break;
                    case SelectStates.Selected_Self:
                    case SelectStates.Selected_By_Parent:
                        res = UriResources.Images.Selected16;
                        break;
                    case SelectStates.Selected_With_Children:
                    case SelectStates.Selected_By_Parent_With_Children:
                    case SelectStates.Labeled_As_Parent:
                    case SelectStates.Selected_With_Children_Has_Excluded:
                    case SelectStates.Selected_By_Parent_With_Children_Has_Excluded:
                        res = UriResources.Images.SelectedChildren16;
                        break;
                    default:
                        break;
                }
            }

            if (memberInfo.Mode == Modes.Filter_Area)
            {
                switch (memberInfo.SelectState)
                {
                    case SelectStates.Not_Initialized:
                    case SelectStates.Not_Selected:
                        res = UriResources.Images.NotSelected16;
                        break;
                    case SelectStates.Selected_By_Parent:
                        res = UriResources.Images.Selected16;
                        break;
                    case SelectStates.Selected_With_Children:
                    case SelectStates.Selected_By_Parent_With_Children:
                        res = UriResources.Images.Selected16;
                        break;
                    case SelectStates.Labeled_As_Parent:
                        res = UriResources.Images.HasSelectedChildren16;
                        break;
                    case SelectStates.Selected_With_Children_Has_Excluded:
                    case SelectStates.Selected_By_Parent_With_Children_Has_Excluded:
                        res = UriResources.Images.HasSelectedChildren16;
                        break;
                    default:
                        break;
                }
            }
            return res;
        }

        /// <summary>
        /// Событие генерируется после окончания выбора элементов иземерения
        /// </summary>
        public event EventHandler ApplySelection;

        /// <summary>
        /// Событие генерируется при нажатии на кнопку Отмена
        /// </summary>
        public event EventHandler CancelSelection;

        /// <summary>
        /// Генерирует событие "Выбор окончен"
        /// </summary>
        private void Raise_ApplySelection()
        {
            EventHandler handler = ApplySelection;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }

        /// <summary>
        /// Генерирует событие "Отмена"
        /// </summary>
        private void Raise_CancelSelection()
        {
            EventHandler handler = CancelSelection;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }

        private void OkButton_Click(object sender, RoutedEventArgs e)
        {
            ApplyMembersSelection();
        }

        private void ApplyMembersSelection()
        {
            GenerateSetBySelectionState();
            //Генерируем событие - выбор окончен
            Raise_ApplySelection();
        }

        private void CancelButton_Click(object sender, RoutedEventArgs e)
        {
            // Генерируем событие - Отмена
            Raise_CancelSelection();
        }

        /// <summary>
        /// Set, сгенерированный по выбранным элементам
        /// </summary>
        private string m_SelectedSet = String.Empty;

        /// <summary>
        /// Set, сгенерированный по выбранным элементам
        /// </summary>
        public String SelectedSet
        {
            get
            {
                return m_SelectedSet;
            }
        }

        /// <summary>
        /// Коллекция для хранения информации о выбранных элементах
        /// </summary>
        private List<MemberChoiceSettings> m_SelectedInfo = null;
        /// <summary>
        /// Информация о выбранных элементах
        /// </summary>
        public List<MemberChoiceSettings> SelectedInfo
        {
            get
            {
                if (m_SelectedInfo == null)
                {
                    m_SelectedInfo = new List<MemberChoiceSettings>();
                }
                return m_SelectedInfo;
            }
            set
            {
                m_SelectedInfo = value;
            }
        }

        /// <summary>
        /// Генерирует Set по иерархии элементов
        /// </summary>
        /// <returns></returns>
        private void GenerateSetBySelectionState()
        {
            if (MultiSelect)
            {
                Dictionary<String, OlapMemberInfo> membersInSet = new Dictionary<String, OlapMemberInfo>();
                String Set = this.OlapMemberInfoHierarchy.GenerateSet(membersInSet);

                if (Set != null && Set.Length > 0)
                {
                    //Убрал HIERARCHIZE Set = "HIERARCHIZE(" + Set + ")";

                    //if (useFilter == true)
                    //{
                    //    if (filterValue != null && filterValue.Length > 0)
                    //    {
                    //        if (filterBeginWith)
                    //            Set = CreateFilterSet(Set, filterValue, 1);
                    //        else
                    //            Set = CreateFilterSet(Set, filterValue, 0);
                    //    }
                    //}
                }

                m_SelectedInfo = new List<MemberChoiceSettings>();
                foreach (OlapMemberInfo memberInfo in membersInSet.Values)
                {
                    MemberChoiceSettings cs = new MemberChoiceSettings(memberInfo.Info, memberInfo.SelectState);
                    m_SelectedInfo.Add(cs);
                }

                //Запоминаем выбранный Set
                if (Set == null || Set.Length <= 0)
                    Set = "{}";

                m_SelectedSet = Set;
            }
            else
            {
                m_SelectedSet = String.Empty;
                SelectedInfo.Clear();

                MemberTreeNode node = null;
                if (tabControl != null && findTab != null && tabControl.SelectedItem == findTab &&
                    findResultTree.SelectedItem != null)
                {
                    node = findResultTree.SelectedItem as MemberTreeNode;
                }
                else
                {
                    node = Tree.SelectedItem as MemberTreeNode;
                }

                if (node != null && node.MemberInfo != null)
                {
                    MemberChoiceSettings cs = new MemberChoiceSettings(node.MemberInfo.Info, SelectStates.Selected_Self);
                    SelectedInfo.Add(cs);

                    //Запоминаем выбранный элемент
                    m_SelectedSet = node.MemberInfo.UniqueName;
                }
            }
        }

        private void FindButton_Click(object sender, RoutedEventArgs e)
        {
            RunSearch();
        }

        /// <summary>
        /// Коллекция элементов, отображаемых в результате поиска
        /// </summary>
        //HybridDictionary foundMembers = new HybridDictionary();

        /// <summary>
        /// Выполняет поиск в кубе
        /// </summary>
        private void RunSearch()
        {
            findResultTree.Items.Clear();
            findResultTree.IsWaiting = true;

            String strToSearch = findTextBox.Text;
            if (!String.IsNullOrEmpty(strToSearch))
            {
                IUserTaskManager taskManager = (IUserTaskManager)Context.Services.GetService(typeof(IUserTaskManager));
                if (taskManager != null)
                {
                    InvokeSchema schema = CommandBuilder.CreateFindMembersCountSchema((string)this.Context.UserData["_$Id"], m_Connection, m_CubeName, HierarchyName, StartLevelUniqueName, StartMemberUniqueName, strToSearch, beginWithCheckBox.IsChecked.Value);

                    taskManager.ProcessTaskItem(Localization.AppTask_FindingMembers,
                        new WaitCallback(InvokeCommandBySchema),
                        new MemberChoiceInvokeSchemaWrapper(schema));
                }
            }
        }

        void FindMembers_InvokeCommandCompleted(InvokeResultSchema res, MemberTreeNode node_)
        {
            findResultTree.IsWaiting = false;

            List<MemberDescriptionWrapper> members = UnPackMembers(res.Content);
            if (members == null)
                return;

            List<OlapMemberInfo> infos = new List<OlapMemberInfo>();

            foreach (MemberDescriptionWrapper wrapper in members)
            {
                // Каждый из элементов помещаем в иерархию
                OlapMemberInfo info = OlapMemberInfoHierarchy.AddMemberToHierarchy(wrapper);
                if (info != null)
                {
                    infos.Add(info);
                }
            }

            Dictionary<String, MemberTreeNode> m_FindTreeNodes = new Dictionary<String, MemberTreeNode>();

            foreach (OlapMemberInfo info in infos)
            {
                MemberTreeNode node = null;

                //Если родительский узел не задан, то узел добавится в корень
                if (m_FindTreeNodes.ContainsKey(info.UniqueName))
                {
                    node = m_FindTreeNodes[info.UniqueName];
                }

                if (node == null)
                {
                    node = new MemberTreeNode(info, MultiSelect);
                    //node.Expanded += new RoutedEventHandler(FindMemberNode_Expanded);
                    m_FindTreeNodes[info.UniqueName] = node;

                    MemberTreeNode parent = null;
                    String parentUniqueName = info.Info.ParentUniqueName;
                    if (!String.IsNullOrEmpty(parentUniqueName))
                    {
                        //Если родительский узел не задан, то узел добавится в корень
                        if (m_FindTreeNodes.ContainsKey(parentUniqueName))
                        {
                            parent = m_FindTreeNodes[parentUniqueName];
                        }
                    }

                    if (parent == null)
                        findResultTree.Items.Add(node);
                    else
                        parent.Items.Add(node);
                }
            }
            findResultTree.UpdateLayout();
        }

        //void FindMemberNode_Expanded(object sender, RoutedEventArgs e)
        //{
        //    MemberTreeNode node = sender as MemberTreeNode;
        //    if (node == null || node.MemberInfo == null)
        //        return;

        //    MemberTreeNode nodeInTree = null;
        //    String uniqueName = node.MemberInfo.UniqueName;
        //    if (!String.IsNullOrEmpty(uniqueName))
        //    { 
        //        // Пытаем найти этот узел среди уже имеющихся в дереве
        //        if (m_TreeNodes.ContainsKey(uniqueName))
        //            nodeInTree = m_TreeNodes[uniqueName];

        //        //Если узел в дереве задан, то нужно просто переключиться на него
        //        if (nodeInTree != null)
        //        {
        //            nodeInTree.IsSelected = true;
        //            tabControl.SelectedIndex = 0;
        //        }
        //    }

        //    //// В случае если узел уже инициализировался и дочерних в кубе у него нет, то при отключенном множетвенном выборе двойной клик считаем выбором элемента
        //    //if (node.IsInialized)
        //    //{
        //    //    if (MultiSelect == false && node.MemberInfo != null && node.MemberInfo.CubeChildrenCount == 0)
        //    //    {
        //    //        ApplyMembersSelection();
        //    //    }
        //    //}
        //}

        private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (tabControl != null && mdxSetTab != null && tabControl.SelectedItem == mdxSetTab)
            {
                GenerateSetBySelectionState();
                mdxSetTextBox.Text = SelectedSet;
            }
        }

    }
}
